﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics.Contracts;

namespace Bamboo.Core
{
    public class RuleManager<TEntity>
    {
        #region Singleton Representation

        static RuleManager()
        {
            Default = new RuleManager<TEntity>();
        }

        public static RuleManager<TEntity> Default { get; private set; }

        private RuleManager()
        {
            this.rules = new List<IRule<TEntity>>();
        }

        #endregion

        private readonly IList<IRule<TEntity>> rules;

        public IEnumerable<IRule<TEntity>> Rules
        {
            get { return this.rules.AsEnumerable(); }
        }

        public RuleManager<TEntity> AddRule(IRule<TEntity> rule)
        {
            this.rules.Add(rule);

            return this;
        }

        public RuleManager<TEntity> AddRule<TRule>()
            where TRule : IRule<TEntity>
        {
            var rule = Activator.CreateInstance<TRule>();

            return this.AddRule(rule);
        }

        public RuleManager<TEntity> RemoveAllRules()
        {
            this.rules.Clear();

            return this;
        }

        public IEnumerable<string> Validate(TEntity entity)
        {
            Contract.Requires(entity != null);

            foreach (var rule in this.rules)
            {
                if (!rule.Validate(entity))
                {
                    yield return rule.Description;
                }
            }
        }
    }
}
